package Engine;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;

public class SPOJ extends JudgeAttributes implements Judge, Runnable {

    public static HashMap<String, Integer> signedInUsers = new HashMap<String, Integer>();

    public SPOJ() {
    }

    public SPOJ(String username, String password, String problemId, String languageId, String code, Long submitLocalId, int runId) {
        this.code = code;
        this.languageId = languageId;
        this.password = password;
        this.problemId = problemId;
        this.submitLocalId = submitLocalId;
        this.runId = runId;
        this.username = username;
        runner = new Thread(this);
        runner.start();
    }

    @Override
    public void run() {
        try {
            switch (runId) {
                case 1: // sign in
                    System.out.println("Signing in ..");
                    signedInUsers.put(username, signIn(username, password) == false ? 0 : 1);
                    System.out.println("Signed in!");
            }
        } catch (Exception e) {
            System.out.println("ERROR!");
        }

    }

    @Override
    public ArrayList<Problem> getAllProblems() throws Exception {
        ArrayList<Problem> ret = new ArrayList<Problem>();
        String[] arr = {"classical", "challenge", "partial", "tutorial"};
        for (int i = 0; i < arr.length; i++) {

            for (int st = 0;; st += 50) {
                URL siteUrl = new URL("http://www.spoj.pl/problems/" + arr[i] + "/sort=0,start=" + st);
                HttpURLConnection conn = (HttpURLConnection) siteUrl.openConnection();
                conn.setRequestMethod("POST");
                conn.setDoOutput(true);
                conn.setDoInput(true);
                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                String line = "";
                int nop = 0;
                while ((line = in.readLine()) != null) {
                    @SuppressWarnings("unused")
                    int ind;
                    if ((ind = line.indexOf("problemrow")) != -1) {
                        int ii = 0;
                        Problem p = new Problem();
                        for (int k = 1; ii < 3; k++) {
                            line = in.readLine();
                            String tem = "";
                            if (k == 3) {
                                int in2 = line.indexOf("\"");
                                for (int j = in2 + 1; line.charAt(j) != '\"'; j++) {
                                    tem += line.charAt(j);
                                }
                                p.setUrl("https://spoj.pl" + tem);
                                int in3 = line.indexOf("<b>");
                                tem = "";
                                for (int j = in3 + 3; j < line.length() && line.charAt(j) != '<'; j++) {
                                    tem += line.charAt(j);
                                }
                                p.setName(tem);
                                break;
                            }
                        }
                        nop++;
                        p.setType(arr[i]);
                        int t = 0;
                        String tem = "";
                        for (int l = 0; l < p.getUrl().length(); l++) {
                            if (t == 4 && p.getUrl().charAt(l) != '/') {
                                tem += p.getUrl().charAt(l);
                            } else if (t > 4) {
                                break;
                            }
                            if (p.getUrl().charAt(l) == '/') {
                                t++;
                            }
                        }
                        p.setId(tem);
                        ret.add(p);
                    }
                }
                System.out.println(ret.size() + " " + i);
                if (nop != 50) {
                    break;
                }
            }
        }
        return ret;
    }

    @Override
    public Submission getLastSubmission(String coderId, String pass, String submissionId) throws Exception {

        return null;

    }

    @Override
    public Problem getProblemInfo(String problemId) throws Exception {
        HashMap<String, Integer> temp = new HashMap<String, Integer>();
        String arr[] = {"Users accepted", "Submissions", "Accepted", "Wrong Answer", "Compile Error", "Runtime Error",
            "Time Limit Exceeded"};
        URL siteUrl = new URL("https://www.spoj.pl/ranks/" + problemId + "/");
        HttpURLConnection conn = (HttpURLConnection) siteUrl.openConnection();
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        conn.setDoInput(true);
        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String line = "";
        int ind = 0;
        boolean flag = false;
        String name = "", id = "/problems/" + problemId + "\">";
        while ((line = in.readLine()) != null) {
            int tem;
            if ((tem = line.indexOf(id)) != -1) {
                for (int k = tem + id.length(); line.charAt(k) != '<'; k++) {
                    name += line.charAt(k);
                }
            }
            if (line.indexOf("lightrow") != -1) {
                flag = true;
            } else if (flag) {
                String n = "";
                for (int i = 0; i < line.length(); i++) {
                    if (line.charAt(i) >= '0' && line.charAt(i) <= '9') {
                        n += line.charAt(i);
                    }
                }
                temp.put(arr[ind++], Integer.parseInt(n));
            }
            if (ind == arr.length) {
                break;
            }
        }
        conn.disconnect();
        Integer x = (temp.get((Object) "Submissions") - temp.get((Object) "Accepted"));
        Problem ret = new Problem(problemId, "http://www.spoj.pl/problems/" + problemId, name, temp.get((Object) "Accepted").toString(), x.toString());
        return ret;
    }

    @Override
    public ArrayList<String> getProblemsSolved(String coderId) throws Exception {
        URL site = new URL("https://www.spoj.pl/users/" + coderId);
        ArrayList<String> ret = new ArrayList<String>();
        HttpURLConnection conn = (HttpURLConnection) site.openConnection();
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        conn.setDoInput(true);
        DataOutputStream out = new DataOutputStream(conn.getOutputStream());;
        out.writeBytes("");
        out.flush();
        out.close();
        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String tem = "";
        StringBuilder page = new StringBuilder();
        while ((tem = in.readLine()) != null) {
            page.append(tem + "\n");
        }
        in.close();
        conn.disconnect();
        int s, ch = 0, chs = 0;
        String f = "<td align=\"left\" width=\"14%\"><a href=";
        String temp = "", prob = "";
        while ((s = page.indexOf(f)) != -1) {
            page.setCharAt(s, '&');
            s += f.length();
            temp = "";
            prob = "";
            ch = chs = 0;
            boolean flagP = false;
            for (int k = s; ch != 2; k++) {
                if (page.charAt(k) == '"') {
                    ch++;
                    continue;
                } else if (page.charAt(k) == '/') {
                    chs++;
                } else if (page.charAt(k) == ',') {
                    flagP = false;
                }

                temp += page.charAt(k);
                if (flagP) {
                    prob += page.charAt(k);
                }
                if (chs == 2) {
                    flagP = true;
                    chs = 0;
                }
            }
            if (prob.equals("")) {
                continue;
            }
            ret.add("https://spoj.pl" + temp);
        }
        return ret;
    }

    @Override
    public void submitProblem(String coderId, String password,
            String problemId, String languageId, String code) throws IOException {
        URL siteUrl = new URL("https://www.spoj.pl/submit/complete/");
        HttpURLConnection conn = (HttpURLConnection) siteUrl.openConnection();
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        conn.setDoInput(true);
        DataOutputStream out = new DataOutputStream(conn.getOutputStream());
        String[] params = {"login_user", "password", "problemcode", "file", "lang", "submit"};
        String[] values = {coderId, password, problemId, code, languageId, "Send"};
        StringBuilder content = new StringBuilder();
        for (int i = 0; i < params.length; i++) {
            if (i != 0) {
                content.append("&");
            }
            content.append(params[i] + "=" + values[i]);
        }
        out.writeBytes(content.toString());
        out.flush();
        out.close();
        conn.getInputStream();
        conn.disconnect();
    }

    @Override
    public boolean signIn(String username, String password) throws Exception {
        PostMethod p = new PostMethod("http://www.spoj.pl/login/");
        p.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
        HttpClient h = new HttpClient();
        h.getParams().setContentCharset("UTF-8");
        p.setParameter("password", password);
        p.setParameter("login_user", username);
        p.setParameter("autologin", "1");
        p.setParameter("submit", "Log In");
        h.getParams().setParameter(
                HttpMethodParams.USER_AGENT,
                "Linux-Omar");
        h.executeMethod(p);
        String tem = p.getResponseBodyAsString();
        if (tem.indexOf("Authentication failed!") != -1) {
            return false;
        }
        return true;
    }

    @Override
    public boolean signOut(String username) {
        return true;
    }

    @Override
    public ArrayList<ProblemText> getProblemTexts() throws Exception {
        ArrayList<ProblemText> ret = new ArrayList<ProblemText>();
        //                                          1           
        String regex = "<p align=\"justify\"> ([\\s\\S]+)((<H3>|<h3>)Input(<H3>|<h3>))([\\s\\S]+)((<H3>|<h3>)Output(<H3>|<h3>))([\\s\\S]+)((<H3>|<h3>)Example(<H3>|<h3>))[\\s\\S]+(<b>(<tt>)?(Sample )?(i|I)nput:(</tt>)?</b>)(<b>(<tt>)?(Sample )?(o|O)utput:(</tt>)?</b>)</pre>";

        return ret;
    }
}
